package com.jinzecloud.reportapproval.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.jinzecloud.reportapproval.bean.ConsCheckRecordInfo;
import com.jinzecloud.reportapproval.bean.KeyInstrument;
import com.jinzecloud.reportapproval.bean.TemperatureHumidity;
import com.jinzecloud.reportapproval.dto.AdminDto;
import com.jinzecloud.reportapproval.dto.AuditParam;
import com.jinzecloud.reportapproval.dto.DataStagingParam;
import com.jinzecloud.reportapproval.enums.AuditRoleEnums;
import com.jinzecloud.reportapproval.enums.StateEnum;
import com.jinzecloud.reportapproval.enums.TableEnums;
import com.jinzecloud.reportapproval.service.*;
import com.jinzecloud.reportapproval.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.io.File;
import java.nio.file.StandardCopyOption;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.jinzecloud.reportapproval.mapper.ConsCheckRecordMapper;
import com.jinzecloud.reportapproval.bean.ConsCheckRecord;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;


@Service("consCheckRecordService")
public class ConsCheckRecordServiceImpl extends ServiceImpl<ConsCheckRecordMapper, ConsCheckRecord> implements ConsCheckRecordService {

    @Autowired
    private ConsCheckRecordInfoService consCheckRecordInfoService;
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private FileUploadUtil fileUploadUtil;

    @Autowired
    private KeyInstrumentService keyInstrumentService;

    @Autowired
    private SoilFirmnessMoistureService soilFirmnessMoistureService;

    @Autowired
    private SpeedOperationTableService speedOperationTableService;

    @Autowired
    private TemperatureHumidityService temperatureHumidityService;

    @Autowired
    private TestsSummaryTableService testsSummaryTableService;

    @Autowired
    private VegetationRecordFormService vegetationRecordFormService;

    @Autowired
    private ConsistencyCheckService consistencyCheckService;

    @Autowired
    private ExperimenttalInvestigationRecordService experimenttalInvestigationRecordService;

    @Autowired
    private DeepStabilityRecordService deepStabilityRecordService;

    @Autowired
    private ProductVerificaRecordService productVerificaRecordService;

    @Autowired
    private UserSurveySummaryService userSurveySummaryService;

    @Autowired
    private BreakageRateService breakageRateService;

    @Autowired
    private SafetyAssessmentService safetyAssessmentService;

    private SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd"); // 原始格式


    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日");


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<ConsCheckRecord> page = this.page(
                new Query<ConsCheckRecord>().getPage(params),
                new QueryWrapper<ConsCheckRecord>().like("product_number", params.get("key")).orderByDesc("id")
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public R addConsCheckRecord(ConsCheckRecord consCheckRecord) {

        // 主表添加成功后
        if (save(consCheckRecord)) {
            List<ConsCheckRecordInfo> consCheckRecordInfoList = consCheckRecord.getConsCheckRecordInfoList();
            for (ConsCheckRecordInfo consCheckRecordInfo : consCheckRecordInfoList) {
                consCheckRecordInfo.setConsCheckRecordId(consCheckRecord.getId());
            }
            consCheckRecordInfoService.saveBatch(consCheckRecordInfoList);
        }

        return R.ok();
    }

    @Override
    @Transactional
    public R updateConsCheckRecord(ConsCheckRecord consCheckRecord) {
        List<ConsCheckRecordInfo> consCheckRecordId = consCheckRecordInfoService.list(new QueryWrapper<ConsCheckRecordInfo>().eq("cons_check_record_id", consCheckRecord.getId()));
        List<Integer> integers = new ArrayList<>();
        if (consCheckRecordId.size() > 0) {
            for (ConsCheckRecordInfo consCheckRecordInfo : consCheckRecordId) {
                integers.add(consCheckRecordInfo.getId());
            }
        }
        if (consCheckRecordInfoService.removeByIds(integers)) {
            // 主表添加成功后
            if (update(consCheckRecord,new QueryWrapper<ConsCheckRecord>().eq("id",consCheckRecord.getId()))) {
                List<ConsCheckRecordInfo> consCheckRecordInfoList = consCheckRecord.getConsCheckRecordInfoList();
                for (ConsCheckRecordInfo consCheckRecordInfo : consCheckRecordInfoList) {
                    consCheckRecordInfo.setConsCheckRecordId(consCheckRecord.getId());
                }
                consCheckRecordInfoService.saveBatch(consCheckRecordInfoList);
            }
        }

        return R.ok();
    }

    @Override
    public String viewPdf(Integer id) {
        ConsCheckRecord checkRecord = getById(id);

        String dataTime = checkRecord.getDataTime();
        try {
            checkRecord.setDataTime(sdf.format(inputFormat.parse(dataTime)));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        List<ConsCheckRecordInfo> consCheckRecordId = consCheckRecordInfoService.list(new QueryWrapper<ConsCheckRecordInfo>().eq("cons_check_record_id", id).orderByAsc("number"));
        checkRecord.setConsCheckRecordInfoList(consCheckRecordId);

        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(checkRecord));

        if (StrUtil.isNotEmpty(data.getString("notekeeper"))) data.put("notekeeper", Pictures.ofUrl(data.getString("notekeeper")).size(30, 10).create());
        if (StrUtil.isNotEmpty(data.getString("inspector"))) data.put("inspector", Pictures.ofUrl(data.getString("inspector")).size(30, 10).create());
        if (StrUtil.isNotEmpty(data.getString("checker"))) data.put("checker", Pictures.ofUrl(data.getString("checker")).size(30, 10).create());


        //word
        File tempFile = WordUtil.getWordFile("template/check_record.docx", data, Configure.builder().bind("consCheckRecordInfoList", policy).useSpringEL());

        if (tempFile == null) return null;
        String fileName = "一致性检查记录表";
        String uploadDirectory = fileUploadUtil.getUploadFilePath("temp");
        String filePath = uploadDirectory + checkRecord.getProductNumber() + fileName;
        String savePath = RequestUtils.getBasePath(request) + "upload/temp/" + checkRecord.getProductNumber() +fileName;
        FileUtil.copyFile(tempFile, new File(filePath + ".docx"),StandardCopyOption.REPLACE_EXISTING);
        PDFUtil.WordToPdf(tempFile, new File(filePath + ".pdf"));

        update(new LambdaUpdateWrapper<ConsCheckRecord>().set(ConsCheckRecord::getWordPath, savePath + ".docx").set(ConsCheckRecord::getPdfPath, savePath + ".pdf").eq(ConsCheckRecord::getId, id));

        return RequestUtils.getBasePath(request) + "upload/temp/" + checkRecord.getProductNumber() + fileName + ".pdf";
    }

    @Override
    public Object auditList(DataStagingParam param) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LambdaQueryWrapper<ConsCheckRecord> queryWrapper = new LambdaQueryWrapper<>();
        List<AdminDto> adminDto = AuditUtil.getAdminDto(authentication.getName());
        Set<Integer> roleSet = adminDto.stream().map(a -> StateEnum.getStateEnumByAuditRole(a.getRoleCode()).getState()).collect(Collectors.toSet());
        roleSet.remove(StateEnum.UN_SUBMIT.getState());
        queryWrapper.in(ConsCheckRecord::getStatus, roleSet);
        return page(new Page<>(param.getPageNo(), param.getPageSize()), queryWrapper);
    }

    @Override
    public R audit(AuditParam auditParam) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        List<AdminDto> adminDos = AuditUtil.getAdminDto(authentication.getName());
        if (CollectionUtil.isEmpty(adminDos)) return R.error("您没有审核权限！");
        ConsCheckRecord consCheckRecord = this.getById(auditParam.getId());
        int state = consCheckRecord.getStatus();
        if (!auditParam.isState()) {
            updateById(consCheckRecord.setStatus(StateEnum.APPROVAL_NOT_PASS.getState())
                    .setAuditOpinion(auditParam.getAuditOpinion())
                    .setAuditDate(DateUtil.date().toDateStr()));
            return R.ok();
        }
        StateEnum currentAuditState = AuditUtil.getStateText(TableEnums.CONS_CHECK_RECORD.getTableName(), state);
        Integer nextAuditStateIndex = AuditUtil.getNextAuditState(TableEnums.CONS_CHECK_RECORD.getTableName(), state, adminDos.stream().map(AdminDto::getRoleCode).toList());
        AdminDto adminDto = adminDos.stream().filter(a -> StrUtil.equals(a.getRoleCode(), currentAuditState.getAuditRole()))
                .findFirst().orElse(null);
        if (adminDto == null || nextAuditStateIndex == null) return R.error("您没有审核权限！");
        if (StrUtil.equals(adminDto.getRoleCode(), AuditRoleEnums.CHECKER_PERSON.getCode())) consCheckRecord.setInspector(adminDto.getAdSignature());
        if (StrUtil.equals(adminDto.getRoleCode(), AuditRoleEnums.RECORDER.getCode())) consCheckRecord.setNotekeeper(adminDto.getAdSignature());
        if (StrUtil.equals(adminDto.getRoleCode(), AuditRoleEnums.CHECKER.getCode())) consCheckRecord.setChecker(adminDto.getAdSignature());
        consCheckRecord.setStatus(nextAuditStateIndex)
                .setAuditOpinion(auditParam.getAuditOpinion())
                .setAuditDate(DateUtil.date().toDateStr());
        updateById(consCheckRecord);
        return R.ok();
    }

    @Override
    public R exportAll(String projectUuid) {
        // 一致性检查记录表
        JSONObject checkRecordJson = checkRecordJson(projectUuid);
        // 主要仪器仪表
        JSONObject keyInstrumentJson = keyInstrumentService.KeyInstrumentJson(projectUuid);
        // 土壤坚实度、土壤含水率测定记录表
        JSONObject soilFirmnessMoistureJson = soilFirmnessMoistureService.soilFirmnessMoistureJson(projectUuid);
        // 气象条件检测记录表
        JSONObject temperatureHumidityJson = temperatureHumidityService.temperatureHumidityJson(projectUuid);
        // 生产试验汇总表
        JSONObject testsSummaryTableJson = testsSummaryTableService.testsSummaryTableJson(projectUuid);
        // 作业速度测定记录表
        JSONObject speedOperationTableJson = speedOperationTableService.speedOperationTableJson(projectUuid);
        // 植被覆盖率测定记录表
        JSONObject vegetationRecordFormJson = vegetationRecordFormService.vegetationRecordFormJson(projectUuid);
        // 产品规格表与产品技术文件一致性检查表
        JSONObject consistencyCheckJson = consistencyCheckService.consistencyCheckJson(projectUuid);
        // 试验田调查记录表
        JSONObject experimenttalInvestigationRecordJson = experimenttalInvestigationRecordService.experimenttalInvestigationRecordJson(projectUuid);
        //耕深、耕深稳定性测定记录表
        JSONObject deepStabilityRecordJson = deepStabilityRecordService.deepStabilityRecordJson(projectUuid);
        //生产查定记录表
        JSONObject productVerificaRecordJson = productVerificaRecordService.productVerificaRecordJson(projectUuid);
        //用户调查汇总表
        JSONObject userSurveySummaryJson = userSurveySummaryService.userSurveySummaryJson(projectUuid);
        //
        JSONObject  breakageRateJson = breakageRateService.checkRecordJson(projectUuid);
        // 安全性检查记录表
        JSONObject safetyAssessmentJson = safetyAssessmentService.safetyAssessmentJson(projectUuid);

        System.out.println(checkRecordJson);

        if (checkRecordJson == null) return R.error(400, "产品：" + projectUuid + " 表2 一致性检查记录表 未填完");
        if (soilFirmnessMoistureJson == null) return R.error(400, "产品：" + projectUuid + " 表7 土壤坚实度、土壤含水率测定记录表 未填完");
        if (temperatureHumidityJson == null) return R.error(400, "产品：" + projectUuid + " 表6 气象条件检测记录表 未填完");
        if (testsSummaryTableJson == null) return R.error(400, "产品：" + projectUuid + " 表13 生产试验汇总表 未填完");
        if (speedOperationTableJson == null) return R.error(400, "产品：" + projectUuid + " 表9 作业速度测定记录表 未填完");
        if (vegetationRecordFormJson == null) return R.error(400, "产品：" + projectUuid + " 表11 植被覆盖率测定记录表 未填完");
        if (consistencyCheckJson == null) return R.error(400, "产品：" + projectUuid + " 表3 产品规格表与产品技术文件一致性检查表 未填完");
        if (experimenttalInvestigationRecordJson == null) return R.error(400, "产品：" + projectUuid + " 表5 试验田调查记录表 未填完");
        if (deepStabilityRecordJson == null) return R.error(400, "产品：" + projectUuid + " 表8 耕深、耕深稳定性测定记录表 未填完");
        if (productVerificaRecordJson == null) return R.error(400, "产品：" + projectUuid + " 表12 生产查定记录表 未填完");
        if (userSurveySummaryJson == null) return R.error(400, "产品：" + projectUuid + " 表14 用户调查汇总表 未填完");
        if (breakageRateJson == null) return R.error(400, "产品：" + projectUuid + " 表10  碎土率测定记录表 未填完");
        if (safetyAssessmentJson == null) return R.error(400, "产品：" + projectUuid + " 表4  安全性检查记录表 未填完");


        // 封装
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("soilFirmnessMoistureJson",soilFirmnessMoistureJson);
        jsonObject.put("productNumber",projectUuid);
        jsonObject.put("checkRecordJson",checkRecordJson);
        jsonObject.put("keyInstrumentJson",keyInstrumentJson);
        jsonObject.put("temperatureHumidityJson",temperatureHumidityJson);
        jsonObject.put("testsSummaryTableJson",testsSummaryTableJson);
        jsonObject.put("speedOperationTableJson",speedOperationTableJson);
        jsonObject.put("vegetationRecordFormJson",vegetationRecordFormJson);
        jsonObject.put("breakageRateJson",breakageRateJson);

        jsonObject.put("consistencyCheckJson",consistencyCheckJson);
        jsonObject.put("experimentJson",experimenttalInvestigationRecordJson);
        jsonObject.put("deepStabilityRecordJson",deepStabilityRecordJson);
        jsonObject.put("productVerificaRecordJson",productVerificaRecordJson);
        jsonObject.put("userSurveySummaryJson",userSurveySummaryJson);

        jsonObject.put("safetyAssessmentJson",safetyAssessmentJson);

        //word
        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        File tempFile = WordUtil.getWordFile("template/rotary_tiller_inspection_record.docx", jsonObject, Configure.builder()
                .bind("keyInstrumentJson.detailList",policy)
                .bind("checkRecordJson.consCheckRecordInfoList",policy)
                .bind("deepStabilityRecordJson.gaugingPoint",policy)
                .bind("productVerificaRecordJson.dataList",policy)
                .useSpringEL());

        if (tempFile == null) return null;
        String fileName = "旋耕机检测记录";
        String uploadDirectory = fileUploadUtil.getUploadFilePath("temp");
        String filePath = uploadDirectory + projectUuid + fileName;
        String savePath = RequestUtils.getBasePath(request) + "upload/temp/" + projectUuid +fileName;


        FileUtil.copyFile(tempFile, new File(filePath + ".docx"), StandardCopyOption.REPLACE_EXISTING);
        PDFUtil.WordToPdf(tempFile, new File(filePath + ".pdf"));

//        update(new LambdaUpdateWrapper<ConsCheckRecord>().set(ConsCheckRecord::getWordPath, savePath + ".docx").set(ConsCheckRecord::getPdfPath, savePath + ".pdf").eq(ConsCheckRecord::getId, id));
        String pdf =  RequestUtils.getBasePath(request) + "upload/temp/" + projectUuid + fileName + ".pdf";
        String word =  RequestUtils.getBasePath(request) + "upload/temp/" + projectUuid + fileName + ".docx";

        return  R.ok().put("pdf",pdf).put("word",word);
    }
    @Override
    public JSONObject checkRecordJson(String projectUuid){
        ConsCheckRecord checkRecord = getOne(new QueryWrapper<ConsCheckRecord>().eq("product_number",projectUuid));
        if(checkRecord == null) return null;
        String dataTime = checkRecord.getDataTime();
        try {
            checkRecord.setDataTime(sdf.format(inputFormat.parse(dataTime)));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        List<ConsCheckRecordInfo> consCheckRecordId = consCheckRecordInfoService.list(new QueryWrapper<ConsCheckRecordInfo>().eq("cons_check_record_id", checkRecord.getId()).orderByAsc("number"));
        checkRecord.setConsCheckRecordInfoList(consCheckRecordId);
        JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(checkRecord));
        return data;
    }

    @Override
    public ConsCheckRecord getProductNumber(String projectNumber) {
        QueryWrapper<ConsCheckRecord> consCheckRecordWrapper = new QueryWrapper<ConsCheckRecord>().eq("product_number", projectNumber);
        ConsCheckRecord consCheckRecord = this.getOne(consCheckRecordWrapper);
        List<ConsCheckRecordInfo> consCheckRecordId = consCheckRecordInfoService.list(new QueryWrapper<ConsCheckRecordInfo>().eq("cons_check_record_id", consCheckRecord.getId()).orderByAsc("number"));

        consCheckRecord.setConsCheckRecordInfoList(consCheckRecordId);
        return consCheckRecord;
    }

//    public static void main(String[] args) {
//        String inputPath = "C:\\Users\\ly\\Desktop\\cxx\\";
//        String outputPath = "C:\\Users\\ly\\Desktop\\cxx\\pdf\\";
//        List<String> inputFiles = Arrays.asList("《安全通论——刷新网络空间安全观》.docx","《变革与规制》.docx","《成长比成功更重要》.docx","《苦难辉煌》.docx");
//
//        for (String inputFile : inputFiles) {
//            PDFUtil.WordToPdf(new File(inputPath+inputFile), new File(outputPath+inputFile.replaceAll("\\.docx$", "")+".pdf"));
//        }
//
//    }
    @Override
    public String viewWord(Integer id) {
        ConsCheckRecord checkRecord = getById(id);

        String dataTime = checkRecord.getDataTime();
        try {
            checkRecord.setDataTime(sdf.format(inputFormat.parse(dataTime)));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        List<ConsCheckRecordInfo> consCheckRecordId = consCheckRecordInfoService.list(new QueryWrapper<ConsCheckRecordInfo>().eq("cons_check_record_id", id).orderByAsc("number"));
        checkRecord.setConsCheckRecordInfoList(consCheckRecordId);

        LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
        JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(checkRecord));

        if (StrUtil.isNotEmpty(data.getString("notekeeper"))) data.put("notekeeper", Pictures.ofUrl(data.getString("notekeeper")).size(30, 10).create());
        if (StrUtil.isNotEmpty(data.getString("inspector"))) data.put("inspector", Pictures.ofUrl(data.getString("inspector")).size(30, 10).create());
        if (StrUtil.isNotEmpty(data.getString("checker"))) data.put("checker", Pictures.ofUrl(data.getString("checker")).size(30, 10).create());


        //word
        File tempFile = WordUtil.getWordFile("template/check_record.docx", data, Configure.builder().bind("consCheckRecordInfoList", policy).useSpringEL());

        if (tempFile == null) return null;
        String fileName = "一致性检查记录表";
        String uploadDirectory = fileUploadUtil.getUploadFilePath("temp");
        String filePath = uploadDirectory + checkRecord.getProductNumber() + fileName;
        String savePath = RequestUtils.getBasePath(request) + "upload/temp/" + checkRecord.getProductNumber() +fileName;
        FileUtil.copyFile(tempFile, new File(filePath + ".docx"),StandardCopyOption.REPLACE_EXISTING);
        PDFUtil.WordToPdf(tempFile, new File(filePath + ".pdf"));

        update(new LambdaUpdateWrapper<ConsCheckRecord>().set(ConsCheckRecord::getWordPath, savePath + ".docx").set(ConsCheckRecord::getPdfPath, savePath + ".pdf").eq(ConsCheckRecord::getId, id));

        return RequestUtils.getBasePath(request) + "upload/temp/" + checkRecord.getProductNumber() + fileName + ".docx";
    }

}
